# -*- coding: utf-8 -*-
"""
Module Description: 请求转发
Date: 2017/12/22
Author:Bai Jin Ping
"""
import base64
import urllib
import urlparse

import jwt
import qiniu as qiniu
from flask import request, make_response

# from pyshare.const.lang_enum import LangEnum
# from pyshare.utils.traceback_utils import print_exc
# from pyshare.framework.firefly_dc.global_errcode import GlobalErrCode
# from pyshare.framework.router.runtime_request_counter import RuntimeRequestCounter
# from pyshare.framework.firefly_dc.globalobject import GlobalObject
from app.const.lang.tips_info import TipsInfo
from framework.async_utils.async_pool import async_pool
from framework.dal.gameconfig.game_env import get_config_env_set
from framework.dal.repository_impl import RoleRepository
from framework.firefly_dc.action_service import ActionService
from framework.firefly_dc.context import _trace_id
from framework.firefly_dc.error_handle import GameException
from framework.firefly_dc.global_errcode import GlobalErrCode
from framework.firefly_dc.request_response import Request, Response
# from pyshare.framework.firefly_dc.action_service import ActionService
# from pyshare.const.lang.tips_info import TipsInfo
# from pyshare.framework.monitor import log_runtime_request_count
# from framework import _trace_id
from app.const.lang_enum import LangEnum
from framework.interceptor.interceptor_chain import InterceptorChain
from utils.traceback_utils import print_exc
from utils.unique_key import create_idx
import json


def parse_request():
    """解析请求参数"""
    token_stat = None
    ip_address = request.remote_addr
    if request.is_json:
        # 解析application/json的参数
        request_args = request.get_json()
    else:
        # 解析application/x-www-form-urlencoded的参数
        temp = urlparse.parse_qs(urllib.unquote(request.form.to_dict()['d']), True)
        request_args = {k: unicode(v[0].encode('unicode_escape').decode('string_escape')) for k, v in temp.iteritems()}

    # 参数key转为小写
    request_args = {(k.lower() if isinstance(k, basestring) else k): v for k, v in request_args.iteritems()}
    # 头部key转为小写
    headers = {(k.lower() if isinstance(k, basestring) else k): v for k, v in request.headers.iteritems()}

    # 客户端的ip会随args发送过来
    if 'ip' in request_args:
        pass
    elif headers.get('ip'):
        request_args['ip'] = headers.get('ip')
    else:
        request_args['ip'] = ip_address

    # 增加traceid获取
    if headers.get('traceid'):
        request_args['traceid'] = headers.get('traceid')
    elif 'traceid' in request_args:
        pass
    else:
        request_args['traceid'] = _trace_id()

    # 语言类型字段
    if 'lang' not in request_args:
        request_args['lang'] = LangEnum.Simplified

    # 增加请求头数据
    if 'appkey' not in request_args:
        request_args['appkey'] = headers.get('app-key', '')

    # 校验token(非接口白名单)
    # action_white_list = get_config_env_set('ActionWhiteList')
    # if request_args.get('actionid') not in action_white_list:
    #     token = request.headers.get('Token')
    #     try:
    #         jwt.decode(
    #             jwt=token,
    #             key="test",
    #             algorithms=["HS256"],
    #         )
    #     except jwt.InvalidSignatureError:
    #         token_stat = GlobalErrCode.Token_ERROR
    #
    #     except jwt.ExpiredSignatureError:
    #         token_stat = GlobalErrCode.EXPIRED_TOKEN
    #
    #     except Exception:
    #         token_stat = GlobalErrCode.Token_ERROR

    return request_args, token_stat

def save_head_logic():
    """保存文件"""
    f = request.files.get('file')
    # 上传到七牛云
    image = f.read()
    # 需要填写你的 Access Key 和 Secret Key
    access_key = 'sub9bq30F4OICDpO02YHAxCaIPfp7MZk4k9iZSJC'
    secret_key = '_ph2ONafasmfwRDBM2CGaeRRRzloozoPUBjfBk5b'
    param_dict = json.loads(urllib.unquote(request.form.to_dict()['d']))
    role_guid = param_dict.get("RoleGuid")
    role_record = RoleRepository.get_by_rid(role_guid)
    if not role_guid or not role_record:
        raise GameException("无角色")
    try:
        # 构建鉴权对象
        q_obj = qiniu.Auth(access_key, secret_key)
        # 要上传的空间
        bucket_name = 'sparkle1'
        # 上传后保存的文件名 生成唯一名
        key = create_idx()
        # 生成上传 Token，可以指定过期时间等
        token = q_obj.upload_token(bucket_name, key, 3600)
        # 要上传文件流
        ret, info = qiniu.put_data(token, key, image)
        if ret.get("key") != key:
            raise GameException("")

    except Exception as e:
        raise GameException(e)

    # 若原已有头像则删除(异步)
    async_pool.submit(delete_old_head_store, key=role_record.head, q=q_obj)

    q_url = get_config_env_set('QiNiuUrl')
    # 保存至角色表中
    role_record.head = q_url + key
    RoleRepository.save(role_record)

    response_obj = Response()
    response_obj.response.update({"Head": q_url + key})
    resp = response_obj.serialize()
    resp_data = make_response(resp)
    return resp_data


def delete_old_head_store(key, q):
    bucket_name = 'sparkle1'
    if not key:
        return
    bucket = qiniu.BucketManager(q)
    ops = qiniu.build_batch_delete(bucket_name, [key])
    bucket.batch(ops)


def forwarding():
    """处理请求的主逻辑"""
    # 构造响应对象
    response_obj = Response()
    # 解析请求参数(校验Token)
    request_args, token_stat = parse_request()
    response_obj.set_lang(request_args['lang'])
    response_obj.set_info(info=TipsInfo.GlobalKeys.authActionDataError, stat=token_stat)
    if not token_stat:
        try:
            # 请求计数
            # RuntimeRequestCounter.increase()
            # log_runtime_request_count(RuntimeRequestCounter.processing_request_count)
            #
            # if not GlobalObject.running:
            #     response_obj.set_info(info=TipsInfo.GlobalKeys.requestFailedPleaseTryAgain, stat=GlobalErrCode.PLEASE_TRY_AGAIN)
            #     return response_obj.serialize()

            request_obj = Request(request_args)

            # 创建拦截器链对象
            interceptor_chain = InterceptorChain()

            # 触发拦截器链前置处理
            if interceptor_chain.apply_pre_process(request=request_obj, response=response_obj):
                # 处理请求
                ActionService.call_target(request=request_obj, response=response_obj)
            # 触发拦截器链后置处理
            interceptor_chain.apply_post_process(request=request_obj, response=response_obj)
        except Exception as e:
            # 最后一道防线,设置无处理异常的默认返回的响应
            response_obj.set_info(info=TipsInfo.GlobalKeys.defaultErrorInfo, stat=GlobalErrCode.ERROR)

            # 打印异常时增加打印请求参数，方便排查
            import json
            print_exc(e, request_args=json.dumps(request_args))
        finally:
            # RuntimeRequestCounter.decrease()
            pass

    """
    增加会话校验
    """

    # 字符串转小写处理
    # gateway_version = request_args.get('gatewayversion').lower()
    # user_center_version = request_args.get('usercenterversion').lower()

    # 网关v2+用户中心v4 才处理
    # if gateway_version.startswith('v2') and user_center_version.startswith('v4'):
    #     # 构造返回对象
    #     resp = response_obj.serialize()
    #     resp_data = make_response(resp)
    #
    #     # 返回头中增加session_token、game_token
    #     resp_data.headers["Session-Token"] = response_obj.headers.get("Session-Token")
    #     resp_data.headers["Game-Token"] = response_obj.headers.get("Game-Token")

    # 走原有逻辑
    # else:
    # 构造返回对象
    resp = response_obj.serialize()
    resp_data = make_response(resp)

    return resp_data
